package org.idtem.component.identificador.engine;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.idtem.UI.IdTemWindowsManager;
import org.idtem.UI.dataTypes.TokenExtendidoUI;
import org.idtem.component.identificador.beans.TokenExtendido;
import org.idtem.component.wordnet.DBSpanishWordNetAPI;
import org.idtem.component.wordnet.datatypes.DataTypeSynset;
import org.idtem.component.wordnet.datatypes.DataTypeVariant;
import org.idtem.utils.constants.Constants;
import org.idtem.utils.dataTypes.Token;
import org.idtem.utils.eagles.EAGLESHelper;
import org.idtem.utils.freeling.RunComandFreeling;
import org.idtem.utils.freeling.SentenciaFreeling;

public class ProcesadorFrase {

	
	public static Collection<TokenExtendido> procesar(String frase) throws Exception {
		Collection<SentenciaFreeling> sentenciasFreeling = RunComandFreeling.analizarInputFrase(frase);
		Collection<Token> tokens = new ArrayList<Token>();
		for (SentenciaFreeling sentenciaFreeling : sentenciasFreeling) {
			tokens.addAll(sentenciaFreeling.getTokens());
		}
		Collection<TokenExtendido> tokensExtendidos = agregarInfoWordnet(tokens);
		return tokensExtendidos;
	}

	/***
	 * Agrega la informacion de realaciones brindadas por wordnet a los distintos tokens
	 * @param tokens
	 * @return
	 * @throws Exception 
	 */
	private static Collection<TokenExtendido> agregarInfoWordnet(Collection<Token> tokens) throws Exception {
		
		ArrayList<TokenExtendido> tokensExtendidos = new ArrayList<TokenExtendido>();
		Collection<TokenExtendidoUI> tokensExtendidosUI = new ArrayList<TokenExtendidoUI>();
		for (Token token : tokens) 
		{
			updateOffsets(token);
			Collection<DataTypeSynset> synsets = obtenerSignificados(token, Constants.IdentificadorConstants.USAR_TODOS_LOS_OFFSETS_DE_CONSULTA);
			Collection<DataTypeSynset> synsetTodos = obtenerSignificados(token, true);
			TokenExtendido tokenExtendido = new TokenExtendido(token, synsets);
			tokensExtendidos.add(tokenExtendido);
			if (Constants.System.VENTANA_DE_DESAMBIGUACION){
				TokenExtendidoUI tokenExtendidoUI = new TokenExtendidoUI(token, synsetTodos);
				tokensExtendidosUI.add(tokenExtendidoUI);
			}
		}
	    
		if (Constants.System.VENTANA_DE_DESAMBIGUACION && !Constants.IdentificadorConstants.USAR_TODOS_LOS_OFFSETS_DE_CONSULTA)
		{
			tokensExtendidosUI = IdTemWindowsManager.SeneseDesambiguationWindow(tokensExtendidosUI);
		    Iterator<TokenExtendido> it = tokensExtendidos.iterator();
		    Iterator<TokenExtendidoUI> itUI = tokensExtendidosUI.iterator();
		    while (it.hasNext() || itUI.hasNext()){
		    	TokenExtendido tokenExtendido = it.next();
		    	TokenExtendidoUI tokenExtendidoUI = itUI.next();
		    	DataTypeSynset selectedSynset = tokenExtendidoUI.getSelectedSynset();
		    	if (selectedSynset != null)
		    	{
			    	String selectedOffset = selectedSynset.getOffset();
			    	if (Constants.IdentificadorConstants.USAR_TODOS_LOS_OFFSETS_DE_CONSULTA)
			    	{
			    		ArrayList<DataTypeSynset> synsetsArray = new ArrayList<DataTypeSynset>(tokenExtendido.getSynsets());
			    		ArrayList<DataTypeSynset> synsetsArrayReordenado = new ArrayList<DataTypeSynset>(synsetsArray.size());
				    	String[] offsets = tokenExtendido.getOffsets();
				    	String[] offsetsReordenado = new String[offsets.length];
				    	offsetsReordenado[0] = selectedOffset;
				    	synsetsArrayReordenado.add(selectedSynset);
				    	int j=1;
				    	for(int i=0; i < offsets.length; i++){
				    		if (!offsets[i].equalsIgnoreCase(selectedOffset)){
				    			offsetsReordenado[j] = offsets[i];
				    			synsetsArrayReordenado.add(j, synsetsArray.get(i));
				    			j++;
				    		}
				    	}
				    	tokenExtendido.setOffsets(offsetsReordenado);
				    	tokenExtendido.setSynsets(synsetsArrayReordenado);
			    	}
			    	else
			    	{
			    		tokenExtendido.setOffsets(new String[]{selectedOffset});
			    		Collection<DataTypeSynset> col = new ArrayList<DataTypeSynset>();
			    		col.add(selectedSynset);
			    		tokenExtendido.setSynsets(col);
			    	}
		    	}
		    }
	    }
		return tokensExtendidos;
	}
	
	/***
	 * Devuelve los sinonimos de un token
	 * @param API
	 * @param token
	 * @return
	 * @throws Exception 
	 */
	private static Collection<DataTypeSynset> obtenerSignificados(Token token, boolean usarTodosLosOffsets) throws Exception{
		Collection<DataTypeSynset> coleccionDeSynset = new ArrayList<DataTypeSynset>();
		DataTypeSynset synset = null;
		
		DBSpanishWordNetAPI API = DBSpanishWordNetAPI.getInstance();
		if (token.getOffsets().length > 0)
		{
			if (EAGLESHelper.isNombre(token.getEagles()) ||
				EAGLESHelper.isVerbo(token.getEagles()) ||
				EAGLESHelper.isAdjetivo(token.getEagles()) ||
				EAGLESHelper.isAdverbio(token.getEagles()))
			{
				for (String offset : token.getOffsets()) 
				{
					synset = API.getSynset(EAGLESHelper.getPOS(token.getEagles()), offset);						
					if (synset != null)
					{
						coleccionDeSynset.add(synset);
						if (!usarTodosLosOffsets){
							//Si no se usan todos los offset entonces obtenemos los synset solo para la primera.
							break;  
						}
					}		
					
				}
	
			}
		}		
		return coleccionDeSynset;
	}
	
	private static void updateOffsets(Token token) {
		String eagles = token.getEagles();
		if (Constants.FreelingConstants.ACTUALIZAR_OFFSETS && (EAGLESHelper.isNombre(eagles) || EAGLESHelper.isAdjetivo(eagles) || EAGLESHelper.isAdverbio(eagles) || EAGLESHelper.isVerbo(eagles)))
		{
			String[] offsets = token.getOffsets();
			ArrayList<String> updateOffsets = new ArrayList<String>();
			for (String offset : offsets) 
			{
				updateOffsets.add(offset);
			}
			Collection<DataTypeVariant> variants = DBSpanishWordNetAPI.getInstance().getVariants(EAGLESHelper.getPOS(eagles), token.getLema());
			for (DataTypeVariant dataTypeVariant : variants) {
				if (updateOffsets.contains(dataTypeVariant.getOffset()) == false)
				{
					updateOffsets.add(dataTypeVariant.getOffset());
				}
			}
			String[] offsetsActualizados = new String[updateOffsets.size()];
			for (int i = 0; i < updateOffsets.size(); i++)
			{
				offsetsActualizados[i] = updateOffsets.get(i);
			}
			token.setOffsets(offsetsActualizados);
		}
		
	}
	
	
}
